#pragma once

class Soulgem {
	friend class SoulgemIterator;
public:
	Soulgem();

	const bool operator ==(const Soulgem& right) const;
	const bool operator !=(const Soulgem& right) const;
	const bool operator < (const Soulgem& right) const;
	const bool operator <=(const Soulgem& right) const;
	const bool operator > (const Soulgem& right) const;
	const bool operator >=(const Soulgem& right) const;

	unsigned int operator & (const unsigned int right) const;
	friend unsigned int operator & (const unsigned int left, const Soulgem& right);

	unsigned int operator | (const Soulgem& right) const;
	unsigned int operator | (const unsigned int right) const;
	friend unsigned int operator | (const unsigned int left, const Soulgem& right);

	unsigned int operator ^ (const unsigned int right) const;
	friend unsigned int operator ^ (const unsigned int left, const Soulgem& right);

	unsigned int operator ! () const;
protected:
	virtual unsigned int level() const = 0;
};

class SoulgemSubLeast : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemSubLeast();
protected:
	unsigned int level() const;
};

static const SoulgemSubLeast subleast = SoulgemSubLeast();

class SoulgemLeast : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemLeast();
protected:
	unsigned int level() const;
};

static const SoulgemLeast least = SoulgemLeast();

class SoulgemLesser : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemLesser();
protected:
	unsigned int level() const;
};

static const SoulgemLesser lesser = SoulgemLesser();

class SoulgemCommon : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemCommon();
protected:
	unsigned int level() const;
};

static const SoulgemCommon common = SoulgemCommon();

class SoulgemGreater : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemGreater();
protected:
	unsigned int level() const;
};

static const SoulgemGreater greater = SoulgemGreater();

class SoulgemGrand : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemGrand();
protected:
	unsigned int level() const;
};

static const SoulgemGrand grand = SoulgemGrand();

class SoulgemUltraGrand : public Soulgem {
	friend class SoulgemIterator;
public:
	SoulgemUltraGrand();
protected:
	unsigned int level() const;
};

static const SoulgemUltraGrand ultra = SoulgemUltraGrand();

class SoulgemIterator : public Soulgem {
public:
	SoulgemIterator(const Soulgem* begin = &subleast);
	SoulgemIterator& operator++();
	SoulgemIterator operator++(int);
	SoulgemIterator& operator--();
	SoulgemIterator operator--(int);

	const Soulgem& operator * () const;
protected:
	unsigned int level() const;
	int lv;
};
